/**
 * kl yy-ds @2021
 */
package com.cxps.server.product.service;

import com.alibaba.fastjson.JSON;
import com.cxps.cloud.common.ConstantPool;
import com.cxps.cloud.message.MyPage;
import com.cxps.server.product.domain.AddCartForm;
import com.cxps.server.product.domain.CartVo;
import com.cxps.server.product.domain.ProductIndex;
import com.cxps.server.product.domain.ProductQuery;
import com.cxps.server.strategy.ContextStrategy;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.Collator;
import java.util.*;

/**
 * 商品列表 业务逻辑层
 *
 * @author YouCai.Liu
 * @since 2021/11/12
 * ...
 */
@Slf4j
@Service
public class ProductService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${cxps.yyds.product-index}")
    private String indexName;

    /**
     * 查询商品列表数据
     */
    public MyPage list(ProductQuery query) throws IOException {
        // 声明返回对象
        MyPage<ProductIndex> page = new MyPage<>();
        page.setSize(query.getSize());
        page.setCurrent(query.getCurrent());
        page.buildCurrent();

        // 创建一个ES查询请求对象
        SearchRequest searchRequest = Requests.searchRequest(indexName);

        // 创建一个搜索资源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        // 构建商品列表查询条件
        QueryBuilder queryBuilder = builderQuery(query);

        // 将条件放入搜索来源
        searchSourceBuilder.query(queryBuilder);

        // 设置分页
        searchSourceBuilder.from(page.getFrom()).size(page.getSize());

        // 设置排序
        String sortBy = query.getSortBy();
        if (StringUtils.isBlank(sortBy)) {
            searchSourceBuilder.sort("id", SortOrder.DESC);
        } else {
            String sortOrder = query.getSortOrder();
            if ("DESC".equals(sortOrder)) {
                searchSourceBuilder.sort(sortBy, SortOrder.DESC);
            } else {
                searchSourceBuilder.sort(sortBy, SortOrder.ASC);
            }
        }

        // 将搜索源放入搜索请求对象
        searchRequest.source(searchSourceBuilder);

        // 调用客户端API进行搜索
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        // 从搜索响应获取结果
        SearchHits hits = searchResponse.getHits();
        SearchHit[] dataHits = hits.getHits();
        if (null == dataHits || dataHits.length == 0) {
            log.error("搜索结果为空");
            return page;
        }

        // 声明返回的集合
        List<ProductIndex> indexList = new ArrayList<>();
        for (SearchHit hit : dataHits) {
            // 每条数据的JSON字符串格式
            String sourceAsString = hit.getSourceAsString();
            log.error(sourceAsString);
            // 将JSON字符串格式的数据转成Java对象
            ProductIndex index = JSON.parseObject(sourceAsString, ProductIndex.class);
            indexList.add(index);
        }
        page.setRecords(indexList);
        page.setTotal(hits.getTotalHits().value);

        return page;
    }

    /**
     * 构建商品查询条件
     * 使用 QueryBuilders 构建 query 条件
     *
     * @return
     */
    private QueryBuilder builderQuery(ProductQuery query) {
        // 创建一个组合查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        // 设置keyword关键字查询模式
        if (StringUtils.isNotBlank(query.getKeyword())) {
            MatchQueryBuilder productName = QueryBuilders.matchQuery("fullText", query.getKeyword());
            boolQueryBuilder.must(productName);
        }

        // 设置价格
        if (StringUtils.isNotBlank(query.getPrice())) {
            // 0-99 100-199
            String[] split = query.getPrice().split("~");
            RangeQueryBuilder productPrice = QueryBuilders.rangeQuery("productPrice").gte(split[0]).lte(split[1]);
            boolQueryBuilder.must(productPrice);
        }

        // 设置类型
        if (StringUtils.isNotBlank(query.getType())) {
            TermQueryBuilder termQuery = QueryBuilders.termQuery("productType", query.getType());
            boolQueryBuilder.must(termQuery);
        }
        return boolQueryBuilder;
    }

    /**
     * 获取查询条件
     *
     * @return
     */
    public Map<String, List<String>> getSearchCondition() {
        // 声明返回的集合
        Map<String, List<String>> map = new HashMap<>();

        // 获取redis操作对象
        ValueOperations valueOperations = redisTemplate.opsForValue();

        // 获取缓存的商品分类
        Object productType = valueOperations.get(ConstantPool.R_PRODUCT_TYPE);
        if (null == productType) {
            // 去数据库查询要缓存的数据
            String str = null;
            valueOperations.set(ConstantPool.R_PRODUCT_TYPE, "null", 30);
        }
        map.put("productType", Lists.newArrayList(productType.toString().split(",")));

        // 获取缓存的XXX
        return map;
    }

    /**
     * 商品收藏
     *
     * @param bizId
     * @return
     */
    public String collectProduct(String bizId) {

        return "SUCCESS";
    }

    /**
     * 加入购物车
     *
     * @param from
     * @return
     */
    public void addCart(AddCartForm from) {
        // 创建key
        String key = ConstantPool.R_CART_INFO + from.getUserId();

        // 获取redis hash 结构的操作对象
        HashOperations hashOperations = redisTemplate.opsForHash();

        // 获取 key 下所有的数据
        Map<Object, Object> entries = hashOperations.entries(key);
        // 如果通过key获取的数据是空，则说明购物车没有任何东西，则新增
        if (null == entries || entries.size() == 0) {
            String hashKey = from.getProductId() + ":" + new Date().getTime();
            hashOperations.put(key, hashKey, 1);
        }else{
            // 判断购物车有没有
            boolean isIncrement = true;

            // 遍历通过key获取的数据
            for (Map.Entry<Object, Object> entry : entries.entrySet()) {
                // 获取每一个hashKey
                String hashKey = entry.getKey().toString();
                // 如果hashKey包含了当前加入的商品ID，则说明已经存在，进行加1
                if(hashKey.contains(from.getProductId())){
                    hashOperations.increment(key, hashKey, 1);
                    isIncrement = false;
                    break;
                }
            }

            // 如果购物车没有，则新增
            if(isIncrement){
                String hashKey = from.getProductId() + ":" + new Date().getTime();
                hashOperations.put(key, hashKey, 1);
            }
        }

    }

    /**
     * 购物车商品数量操作
     * @param from
     */
    public void addCart2(AddCartForm from) {
        // 创建key
        String key = ConstantPool.R_CART_INFO + from.getUserId();

        // 获取redis hash 结构的操作对象
        HashOperations hashOperations = redisTemplate.opsForHash();

        // 获取 key 下所有的数据
        Map<Object, Object> entries = hashOperations.entries(key);
        for (Map.Entry<Object, Object> entry : entries.entrySet()) {
            // 获取每一个hashKey
            String hashKey = entry.getKey().toString();
            // 如果key包含当前操作的商品ID，则直接覆盖
            if(hashKey.contains(from.getProductId())){
                // 直接覆盖
                hashOperations.put(key, hashKey, from.getProductNum());
                break;
            }
        }
    }

    /**
     * 获取用户购物车信息
     *
     * @param userId
     */
    public List<CartVo> getCart(String userId) throws IOException {
        // 创建key
        String key = ConstantPool.R_CART_INFO + userId;

        // 获取redis hash 结构的操作对象
        HashOperations hashOperations = redisTemplate.opsForHash();

        // 购物车清单商品集合
        List<CartVo> cartVos = new ArrayList<>();

        // 从redis查询用户购物车所有商品
        Map<Object, Object> entries = hashOperations.entries(key);
        if (null == entries) {
            return cartVos;
        }

        // 遍历从redis获取的商品集合
        for (Map.Entry<Object, Object> entry : entries.entrySet()) {
            String hashKey = entry.getKey().toString();
            Object productNum = entry.getValue();

            // 将hashKey分隔，取出商品ID和存入的时间戳   商品ID:时间戳
            String[] split = hashKey.split(":");
            String productId = split[0];
            String time = split[1];

            // 购物车单个商品对象
            CartVo cartVo = new CartVo();
            cartVo.setProductId(productId);
            cartVo.setProductNum(Integer.parseInt(productNum.toString()));

            ProductIndex index = getProductByIdToES(productId);
            if (null == index) {
                continue;
            }
            cartVo.setTime(Long.parseLong(time));
            cartVo.setProductName(index.getProductName());
            cartVo.setProductImg(index.getProductImg());
            cartVo.setProductPrice(index.getProductPrice());

            // 计算总价
            BigDecimal b1 = new BigDecimal(cartVo.getProductNum());
            BigDecimal b2 = new BigDecimal(cartVo.getProductPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
            BigDecimal multiply = b1.multiply(b2);
            cartVo.setTotalPrice(multiply.doubleValue());
            cartVos.add(cartVo);
        }

        System.out.println();
        // 将集合按照 集合里对象的 某个字段排序
        Collections.sort(cartVos, ((o1, o2) -> o2.getTime().compareTo(o1.getTime())));

        return cartVos;

    }


    /**
     * 根据商品ID去ES查询商品信息
     *
     * @param productId
     * @return
     * @throws IOException
     */
    private ProductIndex getProductByIdToES(String productId) throws IOException {
        // 去ES查询商品信息
        SearchRequest searchRequest = Requests.searchRequest(indexName);
        // 创建一个搜索资源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.idsQuery().addIds(productId));
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        SearchHit hit = null;
        if (hits.getTotalHits().value == 1) {
            hit = hits.getAt(0);
        } else if (hits.getTotalHits().value > 1) {
            System.out.println("hit too many data");
        }
        if (null == hit) {
            return null;
        }
        String sourceAsString = hit.getSourceAsString();
        // 将JSON字符串格式的数据转成Java对象
        return JSON.parseObject(sourceAsString, ProductIndex.class);
    }

    public static void main(String[] args) {
        List<CartVo> cartVos = new ArrayList<>();

        CartVo c1 = new CartVo();
        c1.setTime(1l);
        cartVos.add(c1);

        CartVo c5 = new CartVo();
        c5.setTime(5l);
        cartVos.add(c5);

        CartVo c3 = new CartVo();
        c3.setTime(3l);
        cartVos.add(c3);

        CartVo c2 = new CartVo();
        c2.setTime(2l);
        cartVos.add(c2);

        System.out.println("排序之前：");
        for (CartVo cartVo : cartVos) {
            System.out.print(cartVo.getTime());
        }

        System.out.println();

        // 将集合按照 集合里对象的 某个字段排序
        Collections.sort(cartVos, ((o1, o2) -> o2.getTime().compareTo(o1.getTime())));

        System.out.println("排序之后：");
        for (CartVo cartVo : cartVos) {
            System.out.print(cartVo.getTime());
        }
    }

    /**
     * 计算价格
     * 根据不同的会员级别打对应的总价折扣
     * V1=0.98
     * V2=0.89
     * V3=0.7
     * @param userId
     * @param selectProductId
     * @return
     */
    public Object jsjg(String userId, String[] selectProductId) {

        // 1、计算出总价
        Double totalPrice = 188.21;

        // 2、查询会员对应的等级
        String vipLevel = "V2";

        // 3、进行折扣
//        if("V1".equals(vipLevel)){
//            Double d = totalPrice * 0.98;
//        }else if("V2".equals(vipLevel)){
//            Double d = totalPrice * 0.89;
//        }else if("V3".equals(vipLevel)){
//            Double d = totalPrice * 0.77;
//        }else if("V4".equals(vipLevel)){
//           Double d = totalPrice * 0.6;
//        }

        ContextStrategy contextStrategy = new ContextStrategy();
        double price = contextStrategy.getPrice(vipLevel, totalPrice);

        return price;
    }
}
